/*
 * Copyright 2011 SWM Services GmbH.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package de.swm.commons.mobile.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.BodyElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.LinkElement;
import com.google.gwt.dom.client.MetaElement;
import com.google.gwt.dom.client.NodeList;

import de.swm.commons.mobile.client.constants.I18NConstants;
import de.swm.commons.mobile.client.setup.OsDetection;
import de.swm.commons.mobile.client.setup.OsDetectionImpl;
import de.swm.commons.mobile.client.setup.Resolution;
import de.swm.commons.mobile.client.setup.ViewPort;
import de.swm.commons.mobile.client.theme.SWMMobileTheme;
import de.swm.commons.mobile.client.theme.base.BaseSWMMobileTheme;
import de.swm.commons.mobile.client.utils.Utils;
import de.swm.gwt.client.exception.ApplicationRedirecter;



/**
 * Base class of the framework. Contains all global settings of the underlying application.
 * 
 */
public final class SWMMobile {

	private static SWMMobileTheme theme;
	private static final OsDetection OS_DETECTION = new OsDetectionImpl();
	private static boolean scrollingDisabled;
	private static I18NConstants i18n = GWT.create(I18NConstants.class);



	/**
	 * Utility constructor.
	 */
	private SWMMobile() {

	}



	/**
	 * Returns the internationalization constants.
	 * 
	 * @return the i18n constants
	 */
	public static I18NConstants getI18N() {
		return i18n;
	}



	/**
	 * Return the current theme of the Application. By default, this will be the base theme.
	 * 
	 * @return the current theme.
	 */
	public static SWMMobileTheme getTheme() {
		if (theme == null) {
			theme = new BaseSWMMobileTheme();
		}
		return theme;
	}



	/**
	 * Sets the current theme of the Application.
	 * 
	 * @param toSet
	 *            the theme to set.
	 */
	public static void setTheme(SWMMobileTheme toSet) {
		theme = toSet;
	}



	public static OsDetection getOsDetection() {
		return OS_DETECTION;
	}



	/**
	 * Sets the css matching the screen resolution.
	 */
	public static void setPageResolutionCSS() {
		int ratio = Utils.getDevicePixelRatio();
		if (ratio == Resolution.HVGA.getRatio()) {
			Document.get().getDocumentElement().setClassName(getTheme().getMGWTCssBundle().getDisplayCss().hvga());
		} else if (ratio == Resolution.WVGA.getRatio()) {
			Document.get().getDocumentElement().setClassName(getTheme().getMGWTCssBundle().getDisplayCss().wvga());
		} else if (ratio == Resolution.QVGA.getRatio()) {
			Document.get().getDocumentElement().setClassName(getTheme().getMGWTCssBundle().getDisplayCss().qvga());
		} else {
			Document.get().getDocumentElement().setClassName(getTheme().getMGWTCssBundle().getDisplayCss().hvga());
		}
	}



	/**
	 * Apply settings for this mgwt app. Every app should call this method with the options its wants for their app
	 * 
	 * The options are documented in @link {@link SWMMobileSettings}
	 * 
	 * @param settings
	 *            the settings for this app
	 * 
	 */
	public static void applySettings(SWMMobileSettings settings) {

		Element head = getHead();

		if (settings.getIconUrl() != null) {
			LinkElement iconUrlLinkElement = Document.get().createLinkElement();
			iconUrlLinkElement.setRel("apple-touch-icon");
			iconUrlLinkElement.setHref(settings.getIconUrl());
			head.appendChild(iconUrlLinkElement);

		}

		if (getOsDetection().isIOs()) {
			MetaElement  numberDetection = Document.get().createMetaElement();
			numberDetection.setName("format-detection");
			numberDetection.setContent("telephone=no");
			head.appendChild(numberDetection);

		}

		if (settings.getStartUrl() != null) {
			LinkElement startUrlLinkElement = Document.get().createLinkElement();
			startUrlLinkElement.setRel("apple-touch-startup-image");
			startUrlLinkElement.setHref(settings.getStartUrl());
			head.appendChild(startUrlLinkElement);
		}

		ViewPort viewPort = settings.getViewPort();

		if (viewPort != null) {
			MetaElement fixViewPortElement = Document.get().createMetaElement();
			fixViewPortElement.setName("viewport");
			fixViewPortElement.setContent(viewPort.getContent());
			head.appendChild(fixViewPortElement);

		}

		if (settings.isFullscreen()) {
			MetaElement fullScreenMetaTag = Document.get().createMetaElement();
			fullScreenMetaTag.setName("apple-mobile-web-app-capable");
			fullScreenMetaTag.setContent("yes");
			head.appendChild(fullScreenMetaTag);
		}

		scrollingDisabled = settings.isPreventScrolling();
		if (settings.isPreventScrolling() && getOsDetection().isIOs()) {
			BodyElement body = Document.get().getBody();
			setupPreventScrolling(body);

		}

		if (settings.isDisablePhoneNumberDetection()) {
			MetaElement fullScreenMetaTag = Document.get().createMetaElement();
			fullScreenMetaTag.setName("format-detection");
			fullScreenMetaTag.setContent("telephone=no");
			head.appendChild(fullScreenMetaTag);
		}

		if (settings.getStatusBarStyle() != null) {
			MetaElement statusBarTag = Document.get().createMetaElement();
			statusBarTag.setName("apple-mobile-web-app-status-bar-style");
			switch (settings.getStatusBarStyle()) {
				case BLACK:
					statusBarTag.setContent("black");
					break;
				case BLACK_TRANSLUCENT:
					statusBarTag.setContent("black-translucent");
					break;
				case DEFAULT:
				default:
					statusBarTag.setContent("default");
					break;
			}

			head.appendChild(statusBarTag);
		}

	}
	
	/**
	 * Checks if client is supported by the application. If the client is not supported, performs redirect.
	 * 
	 * @param clientSupportedAsserter class that performs the support check. Default implementation {@link ClientSupportedAsserter}.
	 * @param redirectUrl URL to redirect to if client is not supported
	 */
	public static void redirectIfClientUnsupported(ClientSupportedAsserter clientSupportedAsserter, String redirectUrl) {
		if (!clientSupportedAsserter.isSupported(getOsDetection())) {
			Utils.console("Unsupported client - redirecting to " + redirectUrl);
			ApplicationRedirecter.redirect(redirectUrl);
		}
	}

	/**
	 * Returns the head.
	 * 
	 * @return the head of the host page.
	 */
	private static Element getHead() {
		NodeList<Element> elementsByTagName = Document.get().getElementsByTagName("head");

		if (elementsByTagName.getLength() != 1) {
			throw new RuntimeException("there is no head element");
		}

		return elementsByTagName.getItem(0);
	}



	/**
	 * Prevents defaults of js event propagation.
	 * 
	 * @param el
	 *            the element for which the default will be prevented.
	 */
	private static native void setupPreventScrolling(Element el)/*-{
																var func = function(event) {
																event.preventDefault();
																return false;
																};

																el.ontouchmove = func;

																}-*/;
	
	/**
	 * Checks if client is supported by SWM-mobile.
	 * 
	 * @author wimmel.guido
	 *
	 */
	public static class ClientSupportedAsserter {
		public boolean isSupported(OsDetection osDetection) {
			return osDetection.isWebkit();
		}
	}

}
